package org.xtext.tcc.serializer;

import com.google.inject.Inject;
import com.google.inject.Provider;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.xtext.serializer.acceptor.ISemanticSequenceAcceptor;
import org.eclipse.xtext.serializer.diagnostic.ISemanticSequencerDiagnosticProvider;
import org.eclipse.xtext.serializer.diagnostic.ISerializationDiagnostic.Acceptor;
import org.eclipse.xtext.serializer.sequencer.AbstractSemanticSequencer;
import org.eclipse.xtext.serializer.sequencer.GenericSequencer;
import org.eclipse.xtext.serializer.sequencer.ISemanticSequencer;
import org.eclipse.xtext.serializer.sequencer.ITransientValueService;
import org.xtext.tcc.services.TccdslGrammarAccess;
import org.xtext.tcc.tccdsl.Attribute;
import org.xtext.tcc.tccdsl.Entity;
import org.xtext.tcc.tccdsl.Function;
import org.xtext.tcc.tccdsl.Model;
import org.xtext.tcc.tccdsl.TccdslPackage;
import org.xtext.tcc.tccdsl.TypeDef;

@SuppressWarnings("restriction")
public class AbstractTccdslSemanticSequencer extends AbstractSemanticSequencer {

	@Inject
	protected TccdslGrammarAccess grammarAccess;
	
	@Inject
	protected ISemanticSequencerDiagnosticProvider diagnosticProvider;
	
	@Inject
	protected ITransientValueService transientValues;
	
	@Inject
	@GenericSequencer
	protected Provider<ISemanticSequencer> genericSequencerProvider;
	
	protected ISemanticSequencer genericSequencer;
	
	
	@Override
	public void init(ISemanticSequencer sequencer, ISemanticSequenceAcceptor sequenceAcceptor, Acceptor errorAcceptor) {
		super.init(sequencer, sequenceAcceptor, errorAcceptor);
		this.genericSequencer = genericSequencerProvider.get();
		this.genericSequencer.init(sequencer, sequenceAcceptor, errorAcceptor);
	}
	
	public void createSequence(EObject context, EObject semanticObject) {
		if(semanticObject.eClass().getEPackage() == TccdslPackage.eINSTANCE) switch(semanticObject.eClass().getClassifierID()) {
			case TccdslPackage.ATTRIBUTE:
				if(context == grammarAccess.getAttributeRule()) {
					sequence_Attribute_Attribute(context, (Attribute) semanticObject); 
					return; 
				}
				else break;
			case TccdslPackage.ENTITY:
				if(context == grammarAccess.getTypeRule() ||
				   context == grammarAccess.getEntityRule()) {
					sequence_Entity_Entity(context, (Entity) semanticObject); 
					return; 
				}
				else break;
			case TccdslPackage.FUNCTION:
				if(context == grammarAccess.getFunctionRule()) {
					sequence_Function_Function(context, (Function) semanticObject); 
					return; 
				}
				else break;
			case TccdslPackage.MODEL:
				if(context == grammarAccess.getModelRule()) {
					sequence_Model_Model(context, (Model) semanticObject); 
					return; 
				}
				else break;
			case TccdslPackage.PACKAGE:
				if(context == grammarAccess.getTypeRule() ||
				   context == grammarAccess.getPackageRule()) {
					sequence_Package_Package(context, (org.xtext.tcc.tccdsl.Package) semanticObject); 
					return; 
				}
				else break;
			case TccdslPackage.TYPE_DEF:
				if(context == grammarAccess.getTypeRule() ||
				   context == grammarAccess.getTypeDefRule()) {
					sequence_TypeDef_TypeDef(context, (TypeDef) semanticObject); 
					return; 
				}
				else break;
			}
		if (errorAcceptor != null) errorAcceptor.accept(diagnosticProvider.createInvalidContextOrTypeDiagnostic(semanticObject, context));
	}
	
	/**
	 * Constraint:
	 *     (type=[Type|ID] many?='*'? name=ID)
	 *
	 * Features:
	 *    type[1, 1]
	 *    many[0, 1]
	 *    name[1, 1]
	 */
	protected void sequence_Attribute_Attribute(EObject context, Attribute semanticObject) {
		genericSequencer.createSequence(context, semanticObject);
	}
	
	
	/**
	 * Constraint:
	 *     (name=ID superEntity=[Entity|ID]? attributes+=Attribute* functions+=Function*)
	 *
	 * Features:
	 *    name[1, 1]
	 *    superEntity[0, 1]
	 *    attributes[0, *]
	 *    functions[0, *]
	 */
	protected void sequence_Entity_Entity(EObject context, Entity semanticObject) {
		genericSequencer.createSequence(context, semanticObject);
	}
	
	
	/**
	 * Constraint:
	 *     ((name=ID parameters+=Attribute*) | (type=[Type|ID] many?='*'? name=ID parameters+=Attribute*))
	 *
	 * Features:
	 *    name[2, 2]
	 *    parameters[0, *]
	 *    type[1, 1]
	 *         MANDATORY_IF_SET many
	 *         EXCLUDE_IF_UNSET name
	 *         MANDATORY_IF_SET name
	 *         MANDATORY_IF_SET parameters
	 *         EXCLUDE_IF_SET name
	 *         EXCLUDE_IF_SET parameters
	 *    many[0, 1]
	 *         EXCLUDE_IF_UNSET type
	 *         EXCLUDE_IF_UNSET name
	 *         EXCLUDE_IF_SET name
	 *         EXCLUDE_IF_SET parameters
	 */
	protected void sequence_Function_Function(EObject context, Function semanticObject) {
		genericSequencer.createSequence(context, semanticObject);
	}
	
	
	/**
	 * Constraint:
	 *     types+=Type*
	 *
	 * Features:
	 *    types[0, *]
	 */
	protected void sequence_Model_Model(EObject context, Model semanticObject) {
		genericSequencer.createSequence(context, semanticObject);
	}
	
	
	/**
	 * Constraint:
	 *     (name=JAVAID types+=Type*)
	 *
	 * Features:
	 *    name[1, 1]
	 *    types[0, *]
	 */
	protected void sequence_Package_Package(EObject context, org.xtext.tcc.tccdsl.Package semanticObject) {
		genericSequencer.createSequence(context, semanticObject);
	}
	
	
	/**
	 * Constraint:
	 *     (name=ID mappedType=JAVAID?)
	 *
	 * Features:
	 *    name[1, 1]
	 *    mappedType[0, 1]
	 */
	protected void sequence_TypeDef_TypeDef(EObject context, TypeDef semanticObject) {
		genericSequencer.createSequence(context, semanticObject);
	}
}
